#Ineffizient
1 + 2 + 3 + 4 + 5 + 6[1] 21
#Effizient
sum(c(1:6))[1] 21
Die Basics für deine BA-Arbeit
Tutorat in deutscher Sprache (Question in English are welcome!)
Dauer: 01.03.2025 09.00 bis 12.00 Uhr, 08.03.2025 09.00 bis 12.00 Uhr
Pause: Nach Bedarf (Bitte Melden)
Fragen jederzeit stellen!
Slides in html, Code kann in Slides kopiert werden
Den Rest schauen wir an, ich helfe gerne!
Geballtes Programm!
Falls ihre etwas vermisst: Kommt am Mittag auf mich zu!!
Tutorat I
Tutorat II
Nehmt diese Grundlagen und Regeln ernst. Es erspart euch viel Zeit und Ärger.
Nachgefragt im Arbeitsmarkt (Industriestandard)
Funktionen oder Loops nutzen
Weshalb? Code muss reproduzierbar sein! Ihr arbeitet nicht bloss einen Tag an eurer Arbeit.
## Überschrift 1 ####Projekt organisieren!
Ich empfehle:
Unsere Daten kommen in verschiedenen Klassen: Numeric, Character und Logical. Zu welcher Klasse ein Datentyp gehört finden wir mit dem class() Befehl heraus.
Alternativ:
Logical: Eine spannende Klasse! Auch damit kann man Rechnen.
Factors geben den Ausprägungen eine Reihenfolge.
Factors können unser Leben schnell vereinfachen. Beispielsweise bei Regressionstabellen oder Visualisierungen.
Mit Base R müssen wir nichts laden. Wir können einfach starten!
Zusätzliche Packages können wir einfach herunterladen.
GitHub hat viele zusätzliche Packages die nicht auf CRAN sind. Dort suchen lohnt sich!
Und was jetzt?
R hat ein Hilfesystem:
Internet hilft auch
Vektoren beinhalten Informationen, können aber nur einer Klasse angehören.
Aber können wir unsere Aufgaben mit Vektoren lösen? Jein.
Lösung: Daten brauchen Kontext: Kombination von Vektoren zu Data Frames.
Data frames sind im Grunde Tabellen, wie wir sie auch aus Excel kennen.
Jede Spalte hat einen Namen (Reihen haben selten auch welche)
Eine Spalte ist ein Vektor
Spalten können verschiedene Klassen haben. Nur eine Klasse pro Spalte.
Reihennummer startet bei 1 (Achtung Python User!)
Spalten werden mit $ ausgewählt. Wenn wir also aus dem iris Datensatz die durchscnittliche Sepal Länge wissen wollen:
Vieles wäre auch in Base R oder mit anderen packages möglich
tidyverse ist in (fast) allem besser
Der Code ist lesbarer und effizienter
Die Pipe ist vereinfacht dein Code massiv!
Sie ist integraler Teil des tidyverse
So funktioniert sie: umschliesst Funktion um Funktion
Schreibweise: |> oder %>%
# A tibble: 3 × 2
Species count
<fct> <int>
1 setosa 50
2 versicolor 50
3 virginica 50
# A tibble: 3 × 2
Species count
<fct> <int>
1 setosa 50
2 versicolor 50
3 virginica 50
Prinzip von Tidy Data:
readr, readxl und havenAchtung: Pfad beachten
Immer wichtig ist genau zu wissen wie eure Daten aussehen:
select()Manchmal müssen wir unsere Daten sortieren. Bspw. um uns besser zu orientieren oder um eine leserliche Tabelle zu exportieren. Dazu nutzen wir arrange().
By default: Aufsteigend
Was machen wenn wir absteigend sortieren wollen?
Oder:
Wir können aber natürlich auch strings (character) alphabetisch sortieren.
Oft müssen wir unsere Daten nach Kriterien filtern. Dazu nutzen wir filter().
Wir nutzen den swiss_popular_bills Datensatz vom schlegel-Package.
Reduziere den Datensatz auf die Variablen date, turnout, no, yes_prop, yes, canton und community. Speicher den neuen Datensatz im Environment.
Wann fand die erste Abstimmung in den Daten statt?
Wie oft war die Zustimmung über 99%?
Welche Gemeinde hatte die höchste Beteiligung im Thurgau?
Aufgabe 1:
Aufgabe 2:
# A tibble: 6 × 8
date bill turnout yes no yes_prop canton community
<date> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 1981-06-14 Gleichstellung von M… 49.4 181 101 64.2 Zürich Aeugst a…
2 1981-06-14 Gleichstellung von M… 34.3 941 595 61.3 Zürich Affolter…
3 1981-06-14 Gleichstellung von M… 33.8 284 156 64.5 Zürich Hausen a…
4 1981-06-14 Gleichstellung von M… 36.6 297 151 66.3 Zürich Hedingen
5 1981-06-14 Gleichstellung von M… 51.2 90 97 48.1 Zürich Kappel a…
6 1981-06-14 Gleichstellung von M… 58.9 194 143 57.6 Zürich Knonau
[1] "1981-06-14"
Aufgabe 3:
# A tibble: 10 × 8
date bill turnout yes no yes_prop canton community
<date> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 1996-03-10 Übertritt Vellerat … 15.6 150 1 99.3 Vaud Servion
2 1996-03-10 Übertritt Vellerat … 52.0 116 1 99.1 Genève Russin
3 2002-06-02 Fristenregelung 54.0 119 1 99.2 Vaud Chavanne…
4 2006-05-21 Bildungsartikel 17.8 130 1 99.2 Solot… Himmelri…
5 2006-05-21 Bildungsartikel 36.3 146 1 99.3 Vaud Bogis-Bo…
6 2006-05-21 Bildungsartikel 44.5 97 1 99.0 Vaud Chavanne…
7 2006-05-21 Bildungsartikel 39.5 271 2 99.3 Vaud Tannay
8 2006-05-21 Bildungsartikel 38.5 126 1 99.2 Vaud Essertin…
9 2012-03-11 Regelung der Geldsp… 60.9 152 1 99.3 Vaud Grancy
10 2012-03-11 Regelung der Geldsp… 58.2 109 1 99.1 Vaud Vinzel
Aufgabe 4:
Aber:
popvotes_red |>
filter(canton == "Thurgau") |>
select(turnout, community) |>
arrange(turnout) |>
head()# A tibble: 6 × 2
turnout community
<chr> <chr>
1 ... Schlatt (TG)
2 ... Warth-Weiningen
3 ... Mammern
4 ... Bottighofen
5 ... Bettwiesen
6 ... Braunau
Nicht lösbar? Was müssten wir tun?
mutate() ist die Basisfunktion für Datentransformationen.
Was mutate macht: Neue Variable
selects2015_red <- select(schlegel::selects2015, gender,
age, canton, education, vote_choice)
selects2015_red |>
mutate(new_variable = "new") |>
head() gender age canton education vote_choice new_variable
1 female 40 Zurich apprenticeship <NA> new
2 female 58 St. Gallen higher vocational degree <NA> new
3 female 28 Zurich (applied/teacher) university FDP new
4 male 24 Thurgau higher vocational degree SVP new
5 male 40 Thurgau apprenticeship FDP new
6 female 31 Zurich (applied/teacher) university GLP new
iris |>
mutate(
relation_petal = Petal.Length / Petal.Width,
relation_septal = Sepal.Length / Sepal.Width) |>
head() Sepal.Length Sepal.Width Petal.Length Petal.Width Species relation_petal
1 5.1 3.5 1.4 0.2 setosa 7.00
2 4.9 3.0 1.4 0.2 setosa 7.00
3 4.7 3.2 1.3 0.2 setosa 6.50
4 4.6 3.1 1.5 0.2 setosa 7.50
5 5.0 3.6 1.4 0.2 setosa 7.00
6 5.4 3.9 1.7 0.4 setosa 4.25
relation_septal
1 1.457143
2 1.633333
3 1.468750
4 1.483871
5 1.388889
6 1.384615
iris2 <- iris
iris2$relation_petal <- iris2$Petal.Length/iris2$Petal.Width
iris2$relation_sepal <- iris2$Sepal.Length/iris2$Sepal.Width
head(iris2) Sepal.Length Sepal.Width Petal.Length Petal.Width Species relation_petal
1 5.1 3.5 1.4 0.2 setosa 7.00
2 4.9 3.0 1.4 0.2 setosa 7.00
3 4.7 3.2 1.3 0.2 setosa 6.50
4 4.6 3.1 1.5 0.2 setosa 7.50
5 5.0 3.6 1.4 0.2 setosa 7.00
6 5.4 3.9 1.7 0.4 setosa 4.25
relation_sepal
1 1.457143
2 1.633333
3 1.468750
4 1.483871
5 1.388889
6 1.384615
Wir können jetzt einfache Variablen erstellen. Aber was wenn wir recodieren wollen?
Die Mitte FDP GLP GPS other SP SVP <NA>
SVP 0 0 0 0 0 0 803 0
FDP 0 688 0 0 0 0 0 0
BDP 129 0 0 0 0 0 0 0
CVP 396 0 0 0 0 0 0 0
GLP 0 0 161 0 0 0 0 0
SP 0 0 0 0 0 749 0 0
GPS 0 0 0 252 0 0 0 0
other 0 0 0 0 409 0 0 0
<NA> 0 0 0 0 0 0 0 1750
Wenn wir Konditionen haben, nutzen wir case_when().
selects2015_red <- selects2015_red |>
mutate(age_cat = case_when(
age < 25 ~ "normal",
age >= 25 & age < 50 ~ "old",
age >= 50 & age < 65 ~ "very old",
age >= 65 ~ "practically dead",
T ~ NA
))
table(selects2015_red$age_cat, useNA = "always")
normal old practically dead very old
775 1870 1173 1432
<NA>
87
Haben wir NA’s gemacht?
Ideen wie wir das checken könnten?
Wenn unsere Kondition nur zwei Ausprägungen hat, nutzen wir ifelse(). Weil wir faul sind…
selects2015_red <- selects2015_red |>
mutate(
geschlecht = ifelse(gender == "male", "Mann", "Frau"))
table(selects2015_red$gender, selects2015_red$geschlecht, useNA = "always")
Frau Mann <NA>
male 0 2561 0
female 2776 0 0
<NA> 0 0 0
Funktioniert aber nur, wenn keine NA vorhanden sind!
selects2015_red <- selects2015_red |>
mutate(
vote_choice_rec =
case_match(
vote_choice,
"BDP" ~ "Die Mitte",
"CVP" ~ "Die Mitte",
.default = vote_choice
),
age_cat = case_when(
age < 25 ~ "normal",
age >= 25 & age < 50 ~ "old",
age >= 50 & age < 65 ~ "very old",
age > 65 ~ "practically dead",
T ~ NA),
geschlecht = ifelse(gender == "male", "Mann", "Frau"))Oft kommen unsere Daten in falschen Formaten. Bspw. numerische Daten als character.
Hier können wir folgende funktionen gut verwenden:
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.9 2.6 16.5 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.9 2.9 17.0 0 1 4 4
Datsun 710 22.8 4 108 93 3.9 2.3 18.6 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.1 3.2 19.4 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.1 3.4 17.0 0 0 3 2
Valiant 18.1 6 225 105 2.8 3.5 20.2 1 0 3 1
Auch hilfreich: everything, starts_with, ends_if
Wir arbeiten wieder mit dem popularvotes Datensatz.
Aufgabe 1:
popvotes_red <- popvotes_red |>
mutate(century= case_when(
year(date) >= 2000 ~ "21st",
year(date) < 2000 ~ "20th",
T ~ NA
))
head(popvotes_red)# A tibble: 6 × 9
date bill turnout yes no yes_prop canton community century
<date> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 1981-06-14 Gleichstellu… 49.4 181 101 64.2 Zürich Aeugst a… 20th
2 1981-06-14 Gleichstellu… 34.3 941 595 61.3 Zürich Affolter… 20th
3 1981-06-14 Gleichstellu… 33.8 284 156 64.5 Zürich Hausen a… 20th
4 1981-06-14 Gleichstellu… 36.6 297 151 66.3 Zürich Hedingen 20th
5 1981-06-14 Gleichstellu… 51.2 90 97 48.1 Zürich Kappel a… 20th
6 1981-06-14 Gleichstellu… 58.9 194 143 57.6 Zürich Knonau 20th
Oder auch weniger effizient:
popvotes_red |>
mutate(century= case_when(
year(date) >= "2000-01-01" ~ "21st",
year(date) < "2000-01-01" ~ "20th",
T ~ NA
)) |>
head()# A tibble: 6 × 9
date bill turnout yes no yes_prop canton community century
<date> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 1981-06-14 Gleichstellu… 49.4 181 101 64.2 Zürich Aeugst a… 20th
2 1981-06-14 Gleichstellu… 34.3 941 595 61.3 Zürich Affolter… 20th
3 1981-06-14 Gleichstellu… 33.8 284 156 64.5 Zürich Hausen a… 20th
4 1981-06-14 Gleichstellu… 36.6 297 151 66.3 Zürich Hedingen 20th
5 1981-06-14 Gleichstellu… 51.2 90 97 48.1 Zürich Kappel a… 20th
6 1981-06-14 Gleichstellu… 58.9 194 143 57.6 Zürich Knonau 20th
Aufgabe 2:
Aufgabe 3:
popvotes_red <- popvotes_red |>
mutate(
yes_num = as.numeric(yes),
no_num = as.numeric(no),
yes_prop_num = as.numeric(yes_prop),
yes_prop_2 = (yes_num / (yes_num + no_num))*100,
test_dif= yes_prop_num - yes_prop_2
)
sum(abs(popvotes_red$test_dif), na.rm = T)[1] 17093.46
Wer weiss wo das Problem ist?
popvotes_red |>
mutate(test_dif= yes_prop_num - round(yes_prop_2, digits = 1)) |>
select(yes_prop, yes_prop_2, test_dif) |>
head()# A tibble: 6 × 3
yes_prop yes_prop_2 test_dif
<chr> <dbl> <dbl>
1 64.2 64.2 0
2 61.3 61.3 0
3 64.5 64.5 0
4 66.3 66.3 0
5 48.1 48.1 0
6 57.6 57.6 0
Stimmts jetzt?
Jetzt wirds spannend. Wir wollen schliesslich aus unseren Daten lernen. Um sie zu aggregieren nutzen wir summarise(). Funktionsweise ist sehr simpel:
In der Regel wollen wir Werte über Grppen erfahren. Wir müssen unsere Daten also gruppieren:
Wir können aber auch nach mehreren Variablen gruppieren:
selects2015_red |>
group_by(gender, age_cat) |>
summarise(mean_age = mean(age, na.rm = T)) |>
na.omit()# A tibble: 8 × 3
# Groups: gender [2]
gender age_cat mean_age
<fct> <chr> <dbl>
1 male normal 20.8
2 male old 37.9
3 male practically dead 73.0
4 male very old 56.4
5 female normal 21.0
6 female old 38.6
7 female practically dead 73.3
8 female very old 56.9
Manchmal muss man die Daten wieder entgruppieren. Das machen wir mit ungroup().
Vereinfacht gibt es zwei Möglichkeiten um Plots zu erstellen:
Base R
ggplot2
Wir nutzen ggplot2 weil:
tidyverse (kann in pipeline genutzt werden)
einfacherer Code
bessere Grafiken
Daten spezifizieren (falls in Pipe weglassen)
x und y Werte spezifizieren in der aes Funktion
Bausteine hinzufügen
Wer zuerst kommt, malt zuerst
geom_bar benötigt nur x-Wertestat = "identity"geom_col nutzenNicht abschliessende Liste:
line
bar
col
point
boxplot
errorbar
smooth
Diskrete Variablen
Kontinuierliche Variablen
Zeitreihen
Verteilung
Effekte
Theoretisch verschiedene Möglichkeiten. Nutzt labs!
Werte nach Spezies darstellen. Wie würdet ihr das machen?
Skalenniveau bestimmt Farbpalette!
Diskret: Qualitative Palette mit unterschiedlichen Farben Kontinuierlich: Divergierende oder Sequenzielle Palette
Siehe hier: https://colorbrewer2.org/
Viele Optionen! Wichtigste sind colorbrewer und viridis
Gruppierte Farbe gehört in aes()! Allgemeine Farbe ausserhalb!
Es gibt zwei Optionen um einzufärben
fill bei Flächencolor bei Linien, Punkten usw.Hier nicht sinnvoll!
Überlappende Datenpunkte verzerren Bild!
Arbeite mit dem Selects Datensatz. Beschreibe die Achsen sinnvoll.
Aufgabe 01
Aufgabe 02
selects |>
group_by(canton, gender) |>
summarise(participation_rate = mean(participation,
na.rm = T)) |>
ggplot(aes(x = canton, y = participation_rate,
fill = gender))+
geom_col(position = "dodge")+
scale_y_continuous(labels = scales::percent)+
theme(axis.text.x = element_text(angle = 50,
hjust = 1))Bei der Datenvisulaisierung gilt: IMMER SINNVOLL SORTIEREN!!
Ideen wo im Code man ansetzen muss?
Ebenfalls möglich: fct_reorder
Wird genau gleich benutzt
Problem: Wir können die Beschriftungen nicht lesen
Wir lösen das Problem indem wir Anpassungen im theme vornehmen.
Grafiken sind nicht das wichtigste! Aber…
scale_y_continous(labels = scales::percent))selects |>
mutate(education2 = case_match(education,
"no graduation" ~ "low education",
"compulsory schooling" ~ "low education",
"apprenticeship" ~ "low education",
"diploma or trading school" ~ "medium education",
"(vocational) matura" ~ "medium education",
"higher vocational degree" ~ "medium education",
"HF" ~ "medium education",
"(applied/teacher) university" ~
"high education")) |>
group_by(canton, gender, education2) |>
tally() |>
na.omit() |>
group_by(canton, gender) |>
mutate(perc = n/ sum(n)) |>
ggplot(aes(x= education2, y= perc, fill= gender))+
geom_col(position = "dodge")+
facet_wrap(~canton)+
scale_y_continuous(labels = scales::percent)+
scale_fill_manual(values = c("dodgerblue", "darkred"),
labels = c("Männer", "Frauen"))+
labs(x= NULL, y= NULL, fill = "Geschlecht",
caption = "low bis apprenticeship; medium bis HF; high alles darüber")+
theme_bw()+
theme(legend.position = "bottom",
axis.text.x = element_text(angle = 90, hjust = 1))
Call:
lm(formula = Sepal.Length ~ Sepal.Width + Species, data = iris)
Residuals:
Min 1Q Median 3Q Max
-1.30711 -0.25713 -0.05325 0.19542 1.41253
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.2514 0.3698 6.089 9.57e-09 ***
Sepal.Width 0.8036 0.1063 7.557 4.19e-12 ***
Speciesversicolor 1.4587 0.1121 13.012 < 2e-16 ***
Speciesvirginica 1.9468 0.1000 19.465 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.438 on 146 degrees of freedom
Multiple R-squared: 0.7259, Adjusted R-squared: 0.7203
F-statistic: 128.9 on 3 and 146 DF, p-value: < 2.2e-16
Veränderungen zwischen Modellen sind hochrelevant!
Die richtigen Gewichte verwenden!
survey_model <- lm(lr_self ~ gender + age,
data = schlegel::selects2015,
weights = weight_total)
summary(survey_model)
Call:
lm(formula = lr_self ~ gender + age, data = schlegel::selects2015,
weights = weight_total)
Weighted Residuals:
Min 1Q Median 3Q Max
-12.1728 -1.4492 -0.0237 1.3817 10.4354
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.244635 0.108282 48.435 < 2e-16 ***
genderfemale -0.674301 0.072140 -9.347 < 2e-16 ***
age 0.011283 0.002001 5.640 1.8e-08 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 2.448 on 4711 degrees of freedom
(623 observations deleted due to missingness)
Multiple R-squared: 0.02429, Adjusted R-squared: 0.02388
F-statistic: 58.65 on 2 and 4711 DF, p-value: < 2.2e-16
Call:
lm(formula = lr_self ~ age * gender, data = selects)
Residuals:
Min 1Q Median 3Q Max
-6.0414 -1.7592 0.1535 2.0226 5.6773
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.134430 0.151725 33.840 < 2e-16 ***
age 0.010425 0.002918 3.572 0.000357 ***
genderfemale -1.204561 0.213766 -5.635 1.85e-08 ***
age:genderfemale 0.011399 0.004100 2.780 0.005457 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 2.594 on 4710 degrees of freedom
(623 observations deleted due to missingness)
Multiple R-squared: 0.02937, Adjusted R-squared: 0.02876
F-statistic: 47.51 on 3 and 4710 DF, p-value: < 2.2e-16
Anpassung notwendig, damit R checkt, dass wir quadrieren wollen: I(variable^2)
Oder neue quadrierte variable vorher erstellen.
Problem: R Output ist nicht schön
Lösung: Tabelle als html oder LaTeX exportieren
Entweder Stargazer oder Texreg eignen sich gut.
Unbedingt immer Koeffizientennamen leserlich machen und sortieren!
Bei binären abhängigen Variablen rechnen wir ein logit Modell. Wieso?
logit_model <- glm(participation ~ gender*age,
data = selects,
family = binomial)
summary(logit_model)
Call:
glm(formula = participation ~ gender * age, family = binomial,
data = selects)
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.656152 0.126185 -5.200 1.99e-07 ***
genderfemale 0.265886 0.171467 1.551 0.120983
age 0.036530 0.002728 13.390 < 2e-16 ***
genderfemale:age -0.012976 0.003600 -3.604 0.000313 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 6332.8 on 5197 degrees of freedom
Residual deviance: 6007.8 on 5194 degrees of freedom
(139 observations deleted due to missingness)
AIC: 6015.8
Number of Fisher Scoring iterations: 4
Logit Modelle können nicht direkt interpretiert werden. Lösung: Vorhergesagte Wahlscheinlichkeiten!
Discrecte changes sind auch nützlich!
Welch Two Sample t-test
data: iris$Sepal.Length and iris$Sepal.Width
t = 36.463, df = 225.68, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
2.63544 2.93656
sample estimates:
mean of x mean of y
5.843333 3.057333
Welch Two Sample t-test
data: iris$Sepal.Length and iris$Sepal.Width
t = 36.463, df = 225.68, p-value < 2.2e-16
alternative hypothesis: true difference in means is greater than 0
95 percent confidence interval:
2.659806 Inf
sample estimates:
mean of x mean of y
5.843333 3.057333
Welch Two Sample t-test
data: iris$Sepal.Length and iris$Sepal.Width
t = 36.463, df = 225.68, p-value = 1
alternative hypothesis: true difference in means is less than 0
95 percent confidence interval:
-Inf 2.912194
sample estimates:
mean of x mean of y
5.843333 3.057333
Nicht verzweifeln, einfach mal googeln!
Mittlerweile gutes Tool
ChatGPT kann auch helfen Code von Google usw zu verstehen!
Viele Wege führen nach Rom.
Nutzt Zitiersoftware!
Overleaf nutzen!
Jede Grafik und Tabelle in der Arbeit untertützt euer Argument!
Anhang dient zur vertieften Information
Theorie bestimmt!
Rubustness checks unterstützen euere Resultate mit anderen Daten
Beispiel meiner MA-Arbeit:
Präsentation der puren Ergebnisse kann oft kurz gehalten werden.
Fragen: - Was heisst das bezgl. meiner Hypothesen? - Was sind mögliche Erklärungen? - Stimmen sie mit der Literatur überein?
kreativer Prozess think critically!!
Signifikanz ist nicht alles!
Schaut euch die Codebooks ganz genau an!
FV Polito, 01.03.2025